if (gtk_widget_get_state_flags (GTK_WIDGET (menu)) != 0)
gtk_widget_set_state_flags (GTK_WIDGET (menu), 0, TRUE);
- /* we don't need to set the style here, since
- * we are a toplevel widget.
- */
+ /* Attach the widget to the toplevel window. */
+ gtk_window_set_attached_to (GTK_WINDOW (menu->priv->toplevel), attach_widget);
/* Fallback title for menu comes from attach widget */
gtk_menu_update_title (menu);
}
g_object_set_data (G_OBJECT (menu), I_(attach_data_key), NULL);
+ /* Detach the toplevel window. */
+ gtk_window_set_attached_to (GTK_WINDOW (menu->priv->toplevel), NULL);
+
g_signal_handlers_disconnect_by_func (data->attach_widget,
(gpointer) attach_widget_screen_changed,
menu);
*/
gchar *name;
+ /* The list of attached windows to this widget.
+ * We keep a list in order to call reset_style to all of them,
+ * recursively. */
+ GList *attached_windows;
+
/* The style for the widget. The style contains the
* colors the widget should be drawn in for each state
* along with graphics contexts used to draw with and
g_return_if_fail (GTK_IS_WIDGET (widget));
reset_style_recurse (widget, NULL);
+
+ g_list_foreach (widget->priv->attached_windows,
+ (GFunc) reset_style_recurse, NULL);
}
#ifdef G_ENABLE_DEBUG
return NULL;
}
+void
+_gtk_widget_add_attached_window (GtkWidget *widget,
+ GtkWindow *window)
+{
+ widget->priv->attached_windows = g_list_prepend (widget->priv->attached_windows, window);
+}
+
+void
+_gtk_widget_remove_attached_window (GtkWidget *widget,
+ GtkWindow *window)
+{
+ widget->priv->attached_windows = g_list_remove (widget->priv->attached_windows, window);
+}
+
/**
* gtk_widget_path_append_for_widget:
* @path: a widget path
* where style properties might be retrieved on that
* situation.
*/
- widget->priv->path = gtk_widget_path_new ();
+ GtkWidget *attach_widget = NULL;
+
+ if (GTK_IS_WINDOW (widget))
+ attach_widget = gtk_window_get_attached_to (GTK_WINDOW (widget));
+
+ if (attach_widget != NULL)
+ widget->priv->path = gtk_widget_path_copy (gtk_widget_get_path (attach_widget));
+ else
+ widget->priv->path = gtk_widget_path_new ();
gtk_widget_path_append_for_widget (widget->priv->path, widget);
}
{
GtkMnemonicHash *mnemonic_hash;
+ GtkWidget *attach_widget;
GtkWidget *default_widget;
GtkWidget *focus_widget;
GtkWindow *transient_parent;
PROP_DELETABLE,
PROP_GRAVITY,
PROP_TRANSIENT_FOR,
+ PROP_ATTACHED_TO,
PROP_OPACITY,
PROP_HAS_RESIZE_GRIP,
PROP_RESIZE_GRIP_VISIBLE,
GTK_TYPE_WINDOW,
GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
+ /**
+ * GtkWindow:attached-to:
+ *
+ * the widget attached to the window.
+ *
+ * Since: 3.4
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_ATTACHED_TO,
+ g_param_spec_object ("attached-to",
+ P_("Attached to Widget"),
+ P_("The widget where the window is attached"),
+ GTK_TYPE_WIDGET,
+ GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
+
/**
* GtkWindow:opacity:
*
case PROP_TRANSIENT_FOR:
gtk_window_set_transient_for (window, g_value_get_object (value));
break;
+ case PROP_ATTACHED_TO:
+ gtk_window_set_attached_to (window, g_value_get_object (value));
+ break;
case PROP_OPACITY:
gtk_window_set_opacity (window, g_value_get_double (value));
break;
case PROP_TRANSIENT_FOR:
g_value_set_object (value, gtk_window_get_transient_for (window));
break;
+ case PROP_ATTACHED_TO:
+ g_value_set_object (value, gtk_window_get_attached_to (window));
+ break;
case PROP_OPACITY:
g_value_set_double (value, gtk_window_get_opacity (window));
break;
return list;
}
+static void
+remove_attach_widget (GtkWindow *window)
+{
+ GtkWindowPrivate *priv = window->priv;
+
+ if (priv->attach_widget)
+ {
+ _gtk_widget_remove_attached_window (priv->attach_widget, window);
+
+ g_object_unref (priv->attach_widget);
+ priv->attach_widget = NULL;
+ }
+}
+
static void
gtk_window_dispose (GObject *object)
{
gtk_window_set_focus (window, NULL);
gtk_window_set_default (window, NULL);
+ remove_attach_widget (GTK_WINDOW (object));
+
G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
}
return window->priv->transient_parent;
}
+/**
+ * gtk_window_set_attached_to:
+ * @window: a #GtkWindow
+ * @attach_widget (allow-none): a #GtkWidget, or %NULL
+ *
+ * Attach the window to a widget. Indicates that @window belongs to @widget.
+ * For example the window of a GtkMenu could belong to a GtkMenuBar or
+ * a GtkEntry or a GtkComboBox, and so on...
+ *
+ * GTK will use this information for styling the @window,
+ * for presenting it as a child of @widget in the accessibility tree
+ * and other things.
+ *
+ * Passing %NULL for @attach_widget detaches the window.
+ *
+ * Since: 3.4
+ **/
+void
+gtk_window_set_attached_to (GtkWindow *window,
+ GtkWidget *attach_widget)
+{
+ GtkWindowPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_WIDGET (window) != attach_widget);
+
+ priv = window->priv;
+
+ remove_attach_widget (window);
+
+ priv->attach_widget = attach_widget;
+
+ if (priv->attach_widget)
+ {
+ _gtk_widget_add_attached_window (priv->attach_widget, window);
+
+ g_object_ref_sink (priv->attach_widget);
+ }
+
+ /* Update the style, as the widget path might change. */
+ gtk_widget_reset_style (GTK_WIDGET (window));
+}
+
+/**
+ * gtk_window_get_attached_to:
+ * @window: a #GtkWindow
+ *
+ * Fetches the attach widget for this window. See
+ * gtk_window_set_attached_to().
+ *
+ * Return value: (transfer none): the widget where the window is attached,
+ * or %NULL if the window is not attached to any widget.
+ *
+ * Since: 3.4
+ **/
+GtkWidget *
+gtk_window_get_attached_to (GtkWindow *window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+ return window->priv->attach_widget;
+}
+
/**
* gtk_window_set_opacity:
* @window: a #GtkWindow
if (priv->transient_parent)
gtk_window_set_transient_for (window, NULL);
+ remove_attach_widget (GTK_WINDOW (widget));
+
/* frees the icons */
gtk_window_set_icon_list (window, NULL);